/*
 * 类Compilation是对整个编译流程的封装
*/

#ifndef RED_SYSTEM_COMPILATION_H
#define RED_SYSTEM_COMPILATION_H

#include "LLVM.h"
#include "Diagnostic.h"
#include "Token.h"
#include <llvm/Support/FormatVariadic.h>
#include <llvm/Target/TargetMachine.h>

using llvm::SMLoc;

class Compilation {
public:
    std::string mainFile;
    llvm::TargetMachine *TM;
    llvm::SourceMgr srcMgr;
    TokenBuffer tokBuf;

    Compilation(std::string filepath, llvm::TargetMachine *target) : mainFile(filepath), TM(target) {}

    void run();

    const char* readFile(const std::string &filepath, SMLoc include_loc);
    Token * tokenizeFile(const std::string &filepath, 
                         Token **end_token, 
                         bool skip_header = false,
                         SMLoc include_loc = SMLoc());

    template <typename... Args>
    void error(const char *loc, unsigned diag_id, Args &&... args) {
        std::string msg = llvm::formatv(getDiagnosticText(diag_id), std::forward<Args>(args)...).str();
        llvm::SourceMgr::DiagKind kind = getDiagnosticKind(diag_id);
        srcMgr.PrintMessage(SMLoc::getFromPointer(loc), kind, msg);
        if (kind == llvm::SourceMgr::DK_Error) {
            assert(false);
            exit(EXIT_FAILURE);
        }
    }
};

#endif /* RED_SYSTEM_COMPILATION_H */
